⚡ 30 秒速记

  • 状态调用提交更新,不返回提交完成承诺
  • 批处理边界与版本影响更新可见时机
  • 当前函数闭包仍保留本轮快照
  • 基于前值计算用函数更新
  • 强制同步是特殊工具,不是日常修补方式

问状态更新同步还是异步,最好拆成调用、计算和提交三个时机。 更新函数可以立即返回,但页面和下一轮状态未必立刻完成;同一回调里的变量也仍是当前渲染快照。批处理随根节点模式和版本变化,不能拿旧定时器案例套所有环境。依赖前一个状态时提交计算函数,想观察更新结果则选择对应的提交后机制,而不是给状态调用加 await。

版本校准: 原理文章中的代码代表特定实现与写作时间。应用到当前项目时,应先确认浏览器、框架或工具的主版本,再区分稳定的规范语义、可变化的内部实现和项目自身约束。

# 从一道面试题说起

这是一道变体繁多的面试题,在 BAT 等一线大厂的面试中考察频率非常高。首先题目会给出一个这样的 App 组件,在它的内部会有如下代码所示的几个不同的 setState 操作:

import React from "react";
import "./styles.css";
export default class App extends React.Component{
  state = {
    count: 0
  }
  increment = () => {
    console.log('increment setState前的count', this.state.count)
    this.setState({
      count: this.state.count + 1
    });
    console.log('increment setState后的count', this.state.count)
  }
  triple = () => {
    console.log('triple setState前的count', this.state.count)
    this.setState({
      count: this.state.count + 1
    });
    this.setState({
      count: this.state.count + 1
    });
    this.setState({
      count: this.state.count + 1
    });
    console.log('triple setState后的count', this.state.count)
  }
  reduce = () => {
    setTimeout(() => {
      console.log('reduce setState前的count', this.state.count)
      this.setState({
        count: this.state.count - 1
      });
      console.log('reduce setState后的count', this.state.count)
    },0);
  }
  render(){
    return <div>
      <button onClick={this.increment}>点我增加</button>
      <button onClick={this.triple}>点我增加三倍</button>
      <button onClick={this.reduce}>点我减少</button>
    </div>
  }
}
webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部